package gui;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

import javax.swing.event.*;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import java.awt.geom.*;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Vector;

import gameManager.*;
import bierki.*;

/**
 * Klasy odpowiedzialne za wygląd interfejsu użytkownika każdego ze stołów
 * @author Konrad Sobczak
 * @author Kamil Nowak
 *
 */

/** 
 * Okienko stołu
 */
class Ramka extends JFrame {
	private JMenuItem koniec;
	private JTextPane chat1do1;
	private JTextField wpisywanie;
	private JScrollPane powPrzewijana;
	private Szachownica szachownica;
	public GameManager menadzer_gry;
	private JPanel panel;
	static SimpleAttributeSet bold = new SimpleAttributeSet();
	static SimpleAttributeSet normal = new SimpleAttributeSet();
	
	/**
	 * Tworzy okienko stołu
	 * @param menadzer - GameManager odpowiedzialny za logikę gry dla tego stołu
	 * @param stan_poczatkowy - stan początkowy - czy gramy białymi czy czarnymi
	 */
	public Ramka(GameManager menadzer, boolean stan_poczatkowy){
		StyleConstants.setBold(bold,true);
		final Ramka ja_sama = this;
		this.setTitle("Szachownica...");
		Toolkit zestaw = Toolkit.getDefaultToolkit();
		Dimension rozmiarEkranu = zestaw.getScreenSize();
		int SZER = rozmiarEkranu.width/3;
		int WYS = SZER+120;
		
		
		JMenu menuPlik = new JMenu("Gra");
		menuPlik.setMnemonic('G');
		koniec = menuPlik.add(new AbstractAction("Koniec"){
			public void actionPerformed(ActionEvent zdarzenie)
				{
				ja_sama.menadzer_gry.zamknij_stol(); 
				ja_sama.setVisible(false);
				ja_sama.dispose();
				}
		});
		
		JMenuBar pasekMenu = new JMenuBar();
		this.setJMenuBar(pasekMenu);
		pasekMenu.add(menuPlik);
		
		
		Container powZawartosci = this.getContentPane();
		
		this.menadzer_gry= menadzer;
		szachownica = new Szachownica(SZER-8, menadzer_gry,stan_poczatkowy);
		
		chat1do1 = new JTextPane();
		chat1do1.setPreferredSize(new Dimension(SZER-10,80));
		chat1do1.setEditable(false);
		powPrzewijana = new JScrollPane(chat1do1);
		
		wpisywanie = new JTextField();
		if(stan_poczatkowy==false)
			wpisywanie.setEnabled(false);
			
		panel=new JPanel();
		panel.setLayout(new BorderLayout());
		
		panel.add(szachownica,BorderLayout.NORTH);
		panel.add(powPrzewijana,BorderLayout.CENTER);
		panel.add(wpisywanie,BorderLayout.SOUTH);
		powZawartosci.add(panel);
		
		wpisywanie.addKeyListener(new UchwytEnteraDlaWpisywania());
		chat1do1.setText("Witamy w grze!!!\nPoniżej możesz wpisywać wiadomości do przeciwnika.\nTak Twoje jak i oponenta wiadomości pojawią się tutaj.");
		this.pack();
		this.setResizable(false);
	}
 
	/** 
	 * Wyswietla okienko informujące o tym, że do gry dołączył przeciwnik, włącza
	 * możliwośc wpisywania komunikatów chat
	 * @param imie - imię przeciwnika, który dołączył do gry
	 */
	public void rozpocznij_gre(String imie){
		JOptionPane.showMessageDialog(this,"Dołączył gracz: " + imie + "\n rozpoczyna sie gra! \nGrasz bialymi, masz pierwszy ruch" ,"Start gry!",JOptionPane.INFORMATION_MESSAGE);
		wpisywanie.setEnabled(true);
		this.setTitle("Szachownica... vs. " + imie);
	}
	
	/**
	 * Wyświetla okienko informujące o końcu gry
	 * @param bo - komunikat skojarzony z końcem gry
	 */
	public void koniec_gry(String bo){
		JOptionPane.showMessageDialog(this,"Koniec gry, " + bo ,"Zwycięzki koniec gry!",JOptionPane.INFORMATION_MESSAGE);
	}
	
	/**
	 * Dodaje wypowiedź do okienka chat
	 * @param kto - nazwa użytkownika przysyłającego komunikat
	 * @param co - treść wypowiedzi
	 */
	public void dodajChatMsg(String kto, String co){
		try{
		String isoco = new String(co.getBytes("iso-8859-2"), "cp1250");
		String isokto = new String(kto.getBytes("iso-8859-2"), "cp1250");
		chat1do1.getDocument().insertString(chat1do1.getDocument().getLength(),"\n" + isokto + ": ",bold);
		chat1do1.getDocument().insertString(chat1do1.getDocument().getLength(),isoco,normal);
		chat1do1.setCaretPosition(chat1do1.getDocument().getLength());
		}
		catch(Exception e){}
	}
	
	
	private class UchwytEnteraDlaWpisywania implements KeyListener{
		public void keyPressed(KeyEvent zdarzenie){
			if(zdarzenie.getKeyCode()==KeyEvent.VK_ENTER){
				if(wpisywanie.getText().length()>0){
					menadzer_gry.sendChatMsg(wpisywanie.getText());
					wpisywanie.setText("");
				}
			}
		}
		
		public void keyReleased(KeyEvent zdarzenie){}
		public void keyTyped(KeyEvent zdarzenie){}
	}

} 

/**
 * Panel odpowiadający za samą szachownicę
 * @author Konrad Sobczak
 * @author Kamil Nowak
 *
 */
class Szachownica  extends JPanel {
	private Point aktualnie_rysowany;
	private Bierka aktualna_bierka;
	private Point poprzedni;
	private Point startowy;
	private Rectangle2D[][] szachownica_graph;
	private GameManager menadzer;
	private Point nierysowane_pole;
	private int poczx,poczy;
	private BierkaKolor moj_kolor_bierki;
	private int SZER;
	
	/**
	 * Tworzy obiekt panelu
	 * @param SZER - szerokość panelu
	 * @param menadzer - GameManager odpowiadający za logikę gry
	 * @param stan_poczatkowy - stan początkowy, czy gramy białymi czy czarnymi
	 */
	public Szachownica(int SZER, GameManager menadzer,boolean stan_poczatkowy){
		super();
			
		this.menadzer=menadzer;
		this.SZER=SZER;
		this.setPreferredSize(new Dimension(SZER,SZER));
		
		startowy=null;
		nierysowane_pole=null;
		aktualnie_rysowany=null;
		aktualna_bierka=null;
		poprzedni=null;
		
		szachownica_graph = new Rectangle2D[8][8];
		
		for(int i=0;i<8;i++){
			for(int j=0;j<8;j++){
				szachownica_graph[i][j]=new Rectangle2D.Double(0+i*SZER/8,0+j*SZER/8,SZER/8,SZER/8);
			}
		}
		
		addMouseListener(new UchwytMyszki());
		addMouseMotionListener(new UchwytRuchuMyszki());
		
		if(stan_poczatkowy)
			this.moj_kolor_bierki=BierkaKolor.CZARNY;
		else{
			this.moj_kolor_bierki=BierkaKolor.BIALY;
		}
	}
	
	/**
	 * Odrysowuje szachownice
	 */
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D)g;
		boolean flaga=true;
		
		for(int i=0;i<8;i++){
			for(int j=0;j<8;j++){
				if(flaga==true){
					g2.setPaint(Color.WHITE);
					g2.fill(szachownica_graph[i][j]);
					
				}
				else{
					g2.setPaint(Color.getHSBColor(125, 125, 125));
					g2.fill(szachownica_graph[i][j]);
				}
				g2.setPaint(Color.BLACK);
				g2.draw(szachownica_graph[i][j]);
				flaga=!flaga;
				
				if(nierysowane_pole!=null && nierysowane_pole.x==i && nierysowane_pole.y==j)
					continue;
				
				if((menadzer.daj_szachownice())[i][j]!=null){
					(menadzer.daj_szachownice())[i][j].narysujSie(g2,(int)szachownica_graph[i][j].getMinX(),(int)szachownica_graph[i][j].getMinY(),SZER/8,SZER/8);
				}
				
			}
			flaga=!flaga;
		}
		
		if(aktualnie_rysowany!=null){
			(menadzer.daj_szachownice())[nierysowane_pole.x][nierysowane_pole.y].narysujSie(g2,aktualnie_rysowany.x,aktualnie_rysowany.y,SZER/8,SZER/8);
		}
	}
	
	/**
	 * Na podstawie pozycji kliknięcia myszką znajduje odpowiednie pole szachownicy
	 * @param x - współrzędna x kliknięcia myszką
	 * @param y - współrzędna y kliknięcia myszką
	 * @return - zwraca współrzędne pola szachownicy, lub null gdy to nie na szachownicy, co w ogólnośći
	 * jest niemożliwe
	 */
	Point znajdz(int x, int y){
		for(int i=0;i<8;i++){
			for(int j=0;j<8;j++){
				if(szachownica_graph[i][j].contains(x, y)){
					return new Point(i,j);
				}
			}
		}
		return null;
	}
	
	private class UchwytMyszki extends MouseAdapter{
		public void mousePressed(MouseEvent zdarzenie){
			int x,y,i,j;
			if(menadzer.get_tura()){
				x=zdarzenie.getX();
				y=zdarzenie.getY();
				Point punkt = znajdz(x,y); //zwroci i,j jako Point (to beda indexy tablicy)
				if((menadzer.daj_szachownice()[punkt.x][punkt.y])!=null)
					if(punkt!=null && menadzer.daj_szachownice()[punkt.x][punkt.y].getKolor()==moj_kolor_bierki){
						System.out.print("tak");
						i=punkt.x;
						j=punkt.y;
						poczx=i;
						poczy=j;
						aktualna_bierka=menadzer.daj_szachownice()[i][j];
						nierysowane_pole=new Point(i,j);
						//startowy=new Point(x,y);
						aktualnie_rysowany=new Point((int)szachownica_graph[i][j].getMinX(),(int)szachownica_graph[i][j].getMinY());
						startowy=new Point((int)szachownica_graph[i][j].getMinX(),(int)szachownica_graph[i][j].getMinY());
						System.out.println("Nacisnieto kwadrat: " + i + " " + j);
						poprzedni=new Point(x,y);
					}
			}
		}
		
		public void mouseReleased(MouseEvent zdarzenie){
			int x,y,i,j;
			if(menadzer.get_tura()){
				x=zdarzenie.getX();
				y=zdarzenie.getY();
				Point punkt = znajdz(x,y); //zwroci i,j jako Point (to beda indexy tablicy)
				if(punkt!=null && aktualna_bierka!=null){
					i=punkt.x;
					j=punkt.y;
					if(menadzer.validate_move(poczx,poczy,i,j)==true){
						System.out.println("sie zwalidowalo");
						menadzer.aktualizuj_szachownice(poczx,poczy,i,j);
						
					}
					
					System.out.println("Puszczono kwadrat: " + i + " " + j);
					
					repaint();
				}
				else{
					
					repaint();
				}
				aktualna_bierka=null;
				startowy=null;
				nierysowane_pole=null;
				startowy=null;
				aktualnie_rysowany=null;
			}
		}
	}
	
	private class UchwytRuchuMyszki implements MouseMotionListener{
		public void mouseMoved(MouseEvent zdarzenie){}
		
		public void mouseDragged(MouseEvent zdarzenie){
			if(menadzer.get_tura()){
				if(aktualna_bierka!=null){
				int dx = aktualnie_rysowany.x - poprzedni.x + zdarzenie.getX();
				int dy = aktualnie_rysowany.y - poprzedni.y + zdarzenie.getY();
				aktualnie_rysowany = new Point(dx,dy);
				poprzedni = new Point(zdarzenie.getX(),zdarzenie.getY());
				}
				repaint();
			}
		}
	}

}
/**
 * interfejs graficzny pojedynczej planszy/szachownicy do gry. Jest to okienko o odpowiednich niezmiennych wymiarach. 
 * 
 * @author Konrad Sobczak
 *
 */
public class ChessTableWindow{
private class PromujPionka extends JPanel{
	  	
		private class Figury  extends JPanel {
		
			private Rectangle2D[] szachownica_graph;
			private int SZER;
		
			
			public Figury(){
				super();
				Toolkit zestaw = Toolkit.getDefaultToolkit();
				Dimension rozmiarEkranu = zestaw.getScreenSize();
				this.SZER = rozmiarEkranu.width/3;	
				this.setPreferredSize(new Dimension(SZER,SZER/8));
				szachownica_graph = new Rectangle2D[8];
				for(int j=0;j<8;j++){
					szachownica_graph[j]=new Rectangle2D.Double(0+j*SZER/8,0,SZER/8,SZER/8);
				}
				addMouseListener(new UchwytMyszki());
			}
			
			public void paintComponent(Graphics g){
				super.paintComponent(g);
				Graphics2D g2 = (Graphics2D)g;
				boolean flaga=true;
			
				for(int j=0;j<8;j++){
					if(flaga==true){
						g2.setPaint(Color.WHITE);
						g2.fill(szachownica_graph[j]);
					}
					else{
						g2.setPaint(Color.getHSBColor(125, 125, 125));
						g2.fill(szachownica_graph[j]);
					}
					g2.setPaint(Color.BLACK);
					g2.draw(szachownica_graph[j]);
				
					if(j<mojeUtraconeBierki.size()){
						mojeUtraconeBierki.get(j).narysujSie(g2,(int)szachownica_graph[j].getMinX(),(int)szachownica_graph[j].getMinY(),SZER/8,SZER/8);
					}
					
					flaga=!flaga;	
				}
			}
			
			Point znajdz(int x, int y){
				for(int j=0;j<8;j++){
					if(szachownica_graph[j].contains(x, y)){
						return new Point(j,j);
					}
				}
				return null;
			}
			
			private class UchwytMyszki extends MouseAdapter{
				public void mouseClicked(MouseEvent zdarzenie){
					if(zdarzenie.getClickCount()>=2){
						Point temp;
						if((temp = znajdz(zdarzenie.getX(),zdarzenie.getY()))!=null){
							wypromowanaBierka=mojeUtraconeBierki.get(temp.x);
							mojeUtraconeBierki.remove(temp.x);
							okno.setVisible(false);
						}
					}
				}
			}
		}
		
		private Bierka wypromowanaBierka=null;
		private JDialog okno;
		private Vector<Bierka> mojeUtraconeBierki;

		public Bierka wypromowanaBierka(){
			return this.wypromowanaBierka;
		}
		
	    public PromujPionka(Vector<Bierka> mojeUtraconeBierki){
	        this.mojeUtraconeBierki=mojeUtraconeBierki;
	    	setLayout(new BorderLayout());
	        JPanel panel = new Figury();
	        add(panel,BorderLayout.CENTER);
	    }
	     
	    public void wyswietlOkno(JFrame rodzic){  
	        if(mojeUtraconeBierki.size()>0){
		    	if(okno == null){
		            okno = new JDialog(rodzic,true);
		            okno.getContentPane().add(this);
		            okno.pack();
		        }
		        
		        okno.setTitle("Awansuj pionka na...");
		        okno.setVisible(true);
	        }
	    }
	    
	}
	
	/**
	 * Powoduje wyślwietlenie okna promocji pionka na figurę, 
	 * @param mojeUtraconeBierki - wektor bierek już utraconych (figur), z których można wybrać tę na którą chemy promować
	 * @return - zwraca bierkę którą wybraliśmy 
	 */
	public  Bierka wypromujOkno(Vector<Bierka> mojeUtraconeBierki){
		PromujPionka promujPionka = new PromujPionka(mojeUtraconeBierki);
		promujPionka.wyswietlOkno(r);
		return promujPionka.wypromowanaBierka();
	}

	Ramka r;
	
	/** 
	 * Wywołuję metodę Ramki wyświetlającą komunukat o rozpoczęciu gry
	 * @param imie - imię gracza który dołączył
	 */
	public  void rozpocznij_gre(String imie){
		r.rozpocznij_gre(imie);
	}
	/**
	 * Wywołuje megodę ramki kończącą grę
	 * @param bo - komunikat skojarzony z końcem gry
	 */
	public  void koniec_gry(String bo){
		r.koniec_gry(bo);
	}
	
	/**
	 * Metoda umożliwiająca zamknięcie okienka z zewnątrz
	 *
	 */
	public void zamknij_z_zewnatrz(){
		r.setVisible(false);
		r.dispose(); 
	}
	/**
	 * Wywoluje repainr() z zewnątrz)
	 *
	 */
	public void repaint(){
		r.repaint();
	}

	/**
	 * Uaktualnia pole chata ogoólnego widoczne na ekranie 

	 * @param kto
	 * @param co
	 */
	public  void dodajChatMsg(String kto, String co){
		r.dodajChatMsg(kto,co);
	}
	
	/** 
	 * Miedy przeciwnik wchodzi na stol ustalamy nowy podpis okna
	 * @param kto tresc lodspisu
	 */
	public  synchronized void setVs(String kto){
		r.setTitle("Szachownica... vs. " + kto);
	}
	
	/**
	 * Umieszcza strong komunikat w odpowowiednich  miejscach chata
	 * @param komunikat
	 */
	public void szach(String komunikat){
		JOptionPane.showMessageDialog(r,komunikat ,"Szach i...",JOptionPane.INFORMATION_MESSAGE);
	}
	
	/**
	 * 
	 * @param g moj menadzer gry, zreszta nie oplcaalalo sie pisac
	 * 
	 * @param stan_poczatkowy - określa czy masz być białymi. Odwołanie do manadzera w  driga srone, dziekije.
	 */
	public ChessTableWindow(GameManager g,boolean stan_poczatkowy){
		r = new Ramka(g,stan_poczatkowy);
		WindowListener windowListener = new WindowAdapter()
		   {   
		   public void windowClosing ( WindowEvent w )
		     {
			 r.menadzer_gry.zamknij_stol(); 
			 r.setVisible(false);
			 r.dispose();
			 }
			  
		   };
		r.addWindowListener( windowListener );
		r.setVisible(true);
		if(!stan_poczatkowy)
			JOptionPane.showMessageDialog(r,"Rozpocząłeś nową grę.\nPóki nikt nie dołączy nic nie będziesz mógł robić\nCzekaj!" ,"Czekaj!",JOptionPane.INFORMATION_MESSAGE);
	}
	
	
}


